package main

import (
	"bgs/cache/redisImp"
	"bgs/component"
	"bgs/conf"
	"bgs/db"
	"bgs/grpc/client"
	grpcImp "bgs/grpc/imp"
	"bgs/nsqp"
	// "bgs/qiniu"
	"bgs/pkg/cos"
	"flag"
	"os"
	"path/filepath"

	"github.com/spf13/pflag"
	"github.com/spf13/viper"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
)

var (
	grpcConf           conf.GrpcSection
	pgConf             conf.PgSection
	redisConf          conf.RedisSection
	wechatConfPtr      *conf.WechatSection
	// qiniuConf          conf.QiniuSection
	cosConfPtr         *conf.CosSection
	nsqConf            conf.NsqSection
	notifierConf       conf.NotifierSection
	wxpayConf          conf.WxpaySection
	inventoryConf      conf.InventorySection
	accountConf        conf.AccountSection
	bilinAdminConf     conf.BilinAdminSection
	bilinProdConf      conf.BilinProdSection
	blingPromotionConf conf.BlingPromotionSection
	varsConfPtr        *conf.VarsSection
	// flagC string
	slog  *zap.SugaredLogger
	pgdao *db.PgDao
)

func main() {
	initLog()
	readConfig()

	slog.Debugf("pgConf => %+v", pgConf)
	slog.Debugf("redisConf => %+v", redisConf)
	slog.Debugf("grpcConf => %+v", grpcConf)
	slog.Debugf("nsqConf => %+v", nsqConf)
	slog.Debugf("notifierConf => %+v", notifierConf)
	slog.Debugf("wechatConf => %+v", *wechatConfPtr)
	slog.Debugf("cosConf => %+v", *cosConfPtr)
	slog.Debugf("wxpayConf => %+v", wxpayConf)
	slog.Debugf("inventoryConf => %+v", inventoryConf)
	slog.Debugf("accountConf => %+v", accountConf)
	slog.Debugf("bilinAdminConf => %+v", bilinAdminConf)
	slog.Debugf("bilinProdConf => %+v", bilinProdConf)
	slog.Debugf("blingPromotionConf => %+v", blingPromotionConf)
	slog.Debugf("varsConf => %+v", *varsConfPtr)

	pgdao = db.New(pgConf, slog)
	// adp := cache.NewAdapter(pgdao, slog) // go-cache
	adp, err := cache.NewRedisAdapter(slog, pgdao, redisConf)
	if err != nil {
		slog.Errorf("cache use redis err:", err.Error())
	}
	// qn := qiniu.NewQiniu(qiniuConf.BucketURI, qiniuConf.AccessKey, qiniuConf.SecretKey)
	cos := cos.NewCos(cosConfPtr)
	componentManger := component.InitComponentManger(slog, pgdao, varsConfPtr, adp, notifierConf, wechatConfPtr)
	if componentManger != nil {
		slog.Infof("components ready")
	}
	// for i := 0; i < 100; i++ {
	// 	chTest := componentManger.Notifier.GetTestWorker()
	// 	chTest <- i
	// }

	clientProxy := client.NewGrpcClientProxy(slog, varsConfPtr, accountConf, bilinAdminConf, bilinProdConf, blingPromotionConf, inventoryConf, wxpayConf)
	slog.Infof("clientProxy ready")
	nsqp.InitNsqServer(nsqConf, pgdao, slog, wechatConfPtr, varsConfPtr, adp, clientProxy, componentManger)
	slog.Infof("nsq server ready")
	grpcImp.InitGRPC(nsqConf, grpcConf, wechatConfPtr, varsConfPtr, pgdao, cos, slog, adp, clientProxy, componentManger)
}

// func initLog2() {
// 	logger, _ := zap.NewProduction()
// 	defer logger.Sync()
// 	zap.ReplaceGlobals(logger)
// 	// logger.Info("initlog", zap.String("name", "hhhhhh"))
// 	slog = zap.S()
// 	slog.Infof("global SugaredLogger after %s", "bgs")
// }

func initLog() {
	c := zap.NewProductionEncoderConfig()
	c.EncodeTime = zapcore.ISO8601TimeEncoder
	c.TimeKey = "time"
	core := zapcore.NewCore(
		zapcore.NewJSONEncoder(c),
		zapcore.AddSync(os.Stdout),
		zap.NewAtomicLevelAt(zap.InfoLevel))
	logger := zap.New(core, zap.AddStacktrace(zapcore.FatalLevel), zap.AddCaller())
	defer logger.Sync()
	zap.ReplaceGlobals(logger)
	// logger.Info("initlog", zap.String("name", "hhhhhh"))
	slog = zap.S()
	slog.Infof("global SugaredLogger after %s", "bgs")
}

func readConfig() {
	flag.String("c", "conf/config.toml", "set configuration `file`")
	pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
	//解析flag
	pflag.Parse()
	//viper绑定pflag
	viper.BindPFlags(pflag.CommandLine)
	viper.SetConfigType("toml")
	configValue := viper.GetString("c")
	viper.AddConfigPath(filepath.Dir(configValue))
	viper.SetConfigName(filepath.Base(configValue))
	// if (configValue != "") {
	// 	slog.Info("use -c")
	// 	viper.AddConfigPath(filepath.Dir(configValue))
	// 	viper.SetConfigName(filepath.Base(configValue))
	// } else {
	// 	slog.Info("not use -c")
	// 	viper.SetConfigName("config")
	// 	viper.SetConfigType("toml")
	// 	viper.AddConfigPath("./")
	// 	viper.AddConfigPath("./conf")
	// 	viper.AddConfigPath("../conf")
	// 	viper.AddConfigPath("../../conf")
	// }

	err := viper.ReadInConfig()
	if err != nil {
		slog.Panicf("Fatal error config file: %s \n", err)
	}

	pgConf = conf.ReadPg(viper.Sub("pg"), slog)
	redisConf = conf.ReadRedis(viper.Sub("redis"), slog)
	grpcConf = conf.ReadGRPC(viper.Sub("grpc"), slog)
	wechatConf := conf.ReadWechat(viper.Sub("wechat"), slog)
	wechatConfPtr = &wechatConf
	// qiniuConf = conf.ReadQiniu(viper.Sub("qiniu"), slog)
	cosConf := conf.ReadCos(viper.Sub("cos"), slog)
	cosConfPtr = &cosConf
	nsqConf = conf.ReadNsq(viper.Sub("nsq"), slog)
	if nsqdAddressFromEnv := os.Getenv(conf.NSQD_ADDRESS_KEY); nsqdAddressFromEnv != "" {
		nsqConf.NsqdAddress = nsqdAddressFromEnv
	}
	notifierConf = conf.ReadNotifier(viper.Sub("notifier"), slog)
	wxpayConf = conf.ReadWxpay(viper.Sub("wxpay"), slog)
	inventoryConf = conf.ReadInventory(viper.Sub("inventory"), slog)
	accountConf = conf.ReadAccount(viper.Sub("account"), slog)
	bilinAdminConf = conf.ReadBilinAdmin(viper.Sub("bilin-admin"), slog)
	bilinProdConf = conf.ReadBilinProd(viper.Sub("bilin-prod"), slog)
	blingPromotionConf = conf.ReadBlingPromotionSection(viper.Sub("bling-promotion"), slog)
	varsConf := conf.ReadVars(viper.Sub("vars"), slog)
	varsConfPtr = &varsConf
}
